<template>
  <div :class="`icon-editor-category ${visualThemeClassName}`">
    <div class="add_cate">
      <el-button
        :link="true"
        type="primary"
        size="default"
        icon="CirclePlus"
        :disabled="userCates.length >= 100"
        @click="addCate()"
      >{{ $demoi18n('icon-editor-category.addCategory') }}</el-button>
    </div>
    <div ref="categories" class="categories">
      <ul>
        <li
          v-for="cate in categories"
          :key="cate.key"
          :class="{ on: cate.isActived }"
          @click="setActiveCate(cate)"
        >
          <div v-if="!cate.isEditing">
            <span class="cate_name" :title="cate.name" @click="setCurCate(cate)">
              <span class="text">{{ cate.name }}</span>
              <i v-if="cate.type==='serverImg' && cate.key !=='custom'" class="count">({{ cate.count||0 }})</i>
            </span>
            <span v-if="cate.isEditable" class="action">
              <el-button
                :link="true"
                size="default"
                icon="EditPen"
                :title="$demoi18n('btn.edit')"
                @click="editCate(cate)"
              ></el-button>
              <el-button
                :link="true"
                size="default"
                icon="Delete"
                :title="$demoi18n('btn.delete')"
                @click="deleteCate(cate)"
              ></el-button>
            </span>
          </div>
          <div v-else class="isEditing">
            <el-input v-model="editingCate.name" size="small"></el-input>
            <span class="action">
              <el-button
                :link="true"
                size="default"
                icon="CircleCheck"
                :title="$demoi18n('panel.confirm.ok')"
                @click="doEditCate(cate)"
              ></el-button>
              <el-button
                :link="true"
                size="default"
                icon="CircleClose"
                :title="$demoi18n('panel.confirm.cancel')"
                @click="cancelEditCate(cate)"
              ></el-button>
            </span>
          </div>
        </li>

        <li v-if="addingCate.isEditing" key="addingCate">
          <div class="isEditing">
            <el-input ref="addingCate_input" v-model="addingCate.name" size="small"></el-input>
            <span class="action">
              <el-button
                :link="true"
                size="default"
                icon="CircleCheck"
                :title="$demoi18n('panel.confirm.ok')"
                @click="doAddCate(cate)"
              ></el-button>
              <el-button
                :link="true"
                size="default"
                icon="Delete"
                :title="$demoi18n('panel.confirm.cancel')"
                @click="cancelAddCate(cate)"
              ></el-button>
            </span>
          </div>
        </li>

      </ul>
    </div>

    <!-- 删除分类弹窗 -->
    <el-dialog
      v-if="deletePopVisible"
      v-model="deletePopVisible"
      :title="$demoi18n('icon-editor-category.confirmDelCate')"
      :class="`delete_icon_cate_dialog ${visualThemeClassName} ${xvueNameSpace}`"
      :close-on-click-modal="false"
      :append-to-body="true"
      :destroy-on-close="true"
      width="350px"
      @close="cancelDeleteCate()"
    >
      <div class="delete_dialog_cont">
        <div style="margin-bottom:20px">{{ $demoi18n('icon-editor-category.categoryName') }}: {{ deletingCate.name }}</div>
        <div class="msg_tip">
          <el-icon><WarningFilled /></el-icon>
          <div v-if="deletingCate.icons.length">{{ $demoi18n('icon-editor-category.cateHasImgWarn') }}</div>
          <div v-else>{{ $demoi18n('icon-editor-category.cateHasNoImg') }}</div>
        </div>
      </div>
      <template #footer>
        <div class="actions">
          <el-button
            v-if="!deletingCate.icons.length"
            size="default"
            type="primary"
            @click="doDeleteCate()"
          >{{ $demoi18n('btn.confirm') }}</el-button>
          <el-button
            v-if="!deletingCate.icons.length"
            size="default"
            @click="cancelDeleteCate()"
          >{{ $demoi18n('btn.cancel') }}</el-button>
          <el-button
            v-if="deletingCate.icons.length"
            size="default"
            type="primary"
            @click="cancelDeleteCate()"
          >{{ $demoi18n('icon-editor-category.gotIt') }}</el-button>
        </div>
      </template>
    </el-dialog>

  </div>
</template>
<script>
import iconApi from '@/apis/iconApi.js';
import iconModes from './icon-modes.js';
import presetCates from './preset-cates.js';
import { nextTick } from 'vue';
import { $demoi18n } from '@/utils/lang';

const errorMap = {
  100104: $demoi18n('icon-editor-category.cateExists'), // 目录已存在
  100106: $demoi18n('icon-editor.maxCateNumExpired'), // 目录数量超限制
};

export default {
  components: {},
  inject: {
    panelWid: {
      default: '',
    },
  },
  props: {
    mode: {
      type: String,
      default: 'all',
    },
  },
  emits: ['curCateChange', 'getSeverCates'],
  data() {
    return {
      xvueNameSpace: process.env.xvueNameSpace, // 给挂载在body下的元素加上主类名
      widgetInstanceId: '',
      tabs: [
        { name: this.$demoi18n('iconEditor.tab.shape'), key: 'vsIcon1', type: 'iconfont', isActived: false, isEditing: false },
        { name: this.$demoi18n('iconEditor.tab.iconfont'), key: 'vsIcon2', type: 'iconfont', isActived: false, isEditing: false },
        { name: this.$demoi18n('icon-editor.tab.rank'), key: 'vsIcon3', type: 'iconfont', isActived: false, isEditing: false },
        { name: this.$demoi18n('iconEditor.tab.customIcon'), key: 'custom', type: 'serverImg', isActived: false, isEditing: false },
      ],
      categories: [],
      curCate: {},
      editingCate: {
        name: '',
      },
      addingCate: {
        name: '',
        isEditing: false,
      },
      deletingCate: {
        key: '',
        name: '',
        icons: [],
      },
      deletePopVisible: false,
    };
  },
  computed: {
    userCates() {
      return this.categories.filter(n => n.isAuto === 0);
    },
  },
  watch: {},
  created() {
    this.initWid();
    this.initIconCates(true);
  },
  mounted() {
    this.setActiveCate(this.tabs[0]);
  },
  methods: {
    initWid() {
      // 本地环境，需要先获取远程环境的token才能用
      this.widgetInstanceId = this.panelWid;
      if (process.env.NODE_ENV === 'development') {
        this.widgetInstanceId = window.pageInfo?.moduleList?.[0]?.uuid;
      }
    },
    transformDefault(obj) {
      const defaultCategory = {
        [presetCates['system']]: this.$demoi18n('iconEditor.tab.systemIcon'),
        [presetCates['line']]: this.$demoi18n('iconEditor.tab.lines'),
        [presetCates['map']]: this.$demoi18n('iconEditor.tab.map'),
      };
      const result = {
        ...obj,
      };
      if (defaultCategory[result.key]) {
        result.name = defaultCategory[result.key];
        result.type = 'serverImgDefault';
        result.isEditable = false;
      }
      return result;
    },
    async initIconCates(isInit) {
      const res = await iconApi.getIconCates();
      const cates = res?.data?.data || [];
      let serverTabs = cates.map(n => this.transformDefault({
        name: n.imageCategoryName,
        key: n.imageCategoryId,
        type: 'serverImg',
        isActived: false,
        isEditing: false,
        isEditable: true,
        isAuto: n.isAuto,
        count: n.count || 0,
      }));

      if (this.mode !== 'map') {
        serverTabs = serverTabs.filter(n => n.key !== presetCates['map']);
      }

      this.$emit('getSeverCates', serverTabs);

      const frontTabs = this.tabs.filter(n => iconModes[this.mode].tabs.includes(n.key));
      const categories = [...frontTabs, ...serverTabs];

      // 将本地图标挪到系统内置图标分类最后面
      const customIndex = categories.findIndex(item => item.key === 'custom');
      if (customIndex >= 0) {
        const customItem = categories[customIndex];
        categories.splice(customIndex, 1);

        let index = categories.findIndex(n => n.isAuto === 0);
        if (index === -1) {
          index = categories.length;
        }
        categories.splice(index, 0, customItem);
      }

      this.categories = categories;

      if (isInit) {
        this.setActiveCate(this.categories[0]);
      }
    },
    async updateImgCounts() {
      const res = await iconApi.getIconCates();
      const cates = res?.data?.data || [];
      cates.forEach(n => {
        this.categories.forEach(n1 => {
          if (n.imageCategoryId === n1.key) {
            n1.count = n.count || 0;
          }
        });
      });
    },
    addCate() {
      this.addingCate.name = '';
      this.addingCate.isEditing = true;
      nextTick(() => {
        const el = this.$refs['categories'];
        el.scrollTop = el.scrollHeight;
        this.$refs['addingCate_input'].focus();
      });
    },
    checkName(_name) {
      const name = _name.trim();
      const reg = /^[\u0e00-\u0e7f\u4e00-\u9fa5\w\ \(\)\-\（\）]*$/; // 分类名称只允许输入中文，英文，数字，下划线_，空格，小括号 (), 中文括号 （） 和连字符 -
      const max = 50;
      const min = 1;
      let result = true;
      if (!new RegExp(reg).test(name)) {
        this.$message.warning(this.$demoi18n('iconEditor.cateAllowInputChars'));
        result = false;
      }
      if (name.length < min || name.length > max) {
        this.$message.warning(this.$demoi18n('panel.rules.maxMinRule', [this.$demoi18n('word.category'), max, min]));
        result = false;
      }
      return result;
    },
    async doAddCate() {
      if (!this.checkName(this.addingCate.name)) {
        return;
      }
      const res = await iconApi.addIconCate(this.addingCate.name);
      const { code } = res.data;
      if (code === 200) {
        this.categories.push({
          name: this.addingCate.name,
          key: res.data.data,
          type: 'serverImg',
          isActived: false,
          isEditing: false,
          isEditable: true,
          isAuto: 0,
          count: 0,
        });
        this.addingCate.name = '';
        this.addingCate.isEditing = false;

        // 删除和添加后重新调用接口刷新tabs
        this.initIconCates();
        return;
      }

      const msg = errorMap[code] || res.message;
      this.$message.error(msg);
    },
    cancelAddCate() {
      this.addingCate.name = '';
      this.addingCate.isEditing = false;
    },
    setActiveCate(cate) {
      this.categories.forEach(n => {
        n.isActived = false;
      });
      cate.isActived = true;
      this.curCate = cate;
      this.$emit('curCateChange', cate);
    },
    editCate(cate) {
      this.categories.forEach(n => {
        n.isEditing = false;
      });
      this.editingCate = { ...cate };
      cate.isEditing = true;
    },
    async doEditCate(cate) {
      if (!this.checkName(this.editingCate.name)) {
        return;
      }
      if (cate.name === this.editingCate.name) {
        cate.isEditing = false;
        return;
      }

      const res = await iconApi.editIconCate({
        id: cate.key,
        name: this.editingCate.name,
      });

      const { code } = res.data;
      if (code === 200) {
        cate.name = this.editingCate.name;
        cate.isEditing = false;
        return;
      }

      if (code === 100104) {
        this.$message.error(this.$demoi18n('icon-editor-category.cateExists'));
      }
      if (code === 70001) {
        this.$message.error(this.$demoi18n('icon-editor-category.unsupported'));
      }
    },
    cancelEditCate(cate) {
      cate.isEditing = false;
    },
    async deleteCate(cate) {
      const res = await iconApi.getIconsInCate({ cateId: cate.key, pageSize: 1 });
      this.deletingCate.name = cate.name;
      this.deletingCate.key = cate.key;
      this.deletingCate.icons = res?.data?.data?.list || [];
      this.deletePopVisible = true;
    },
    async doDeleteCate() {
      const res = await iconApi.deleteIconCate(this.deletingCate.key);
      this.categories = this.categories.filter(n => n.key !== this.deletingCate.key);
      this.$message.success(this.$demoi18n('icon-editor-category.deleteSuccess'));
      this.deletePopVisible = false;

      // 删除和添加后重新调用接口刷新tabs
      this.initIconCates();
    },
    cancelDeleteCate() {
      this.deletePopVisible = false;
    },
    setCurCate(cate) {
      this.categories.forEach(n => {
        n.isEditing = false;
      });
      cate.isActived = true;
      this.curCate = cate;
    },
  },
};
</script>
<style lang="less" scoped>
.visualComponents_theme_light{
  --border-color: #e8e8e8;
  --item-on-bg-color: #e0eeff;
  --item-hover-color: #3b8df3;
  --action-btn-color: #333;
}
.visualComponents_theme_dark{
  --border-color: #588ba8;
  --item-on-bg-color: #000000;
  --item-hover-color: #00f0ff;
  --action-btn-color: #00f0ff;
}

.icon-editor-category{
  border-right: 1px solid var(--border-color);
  width: 200px;
  display: flex;
  flex-direction: column;
  .add_cate{
    border-bottom: 1px solid var(--border-color);
    height: 36px;
    line-height: 36px;
  }
  .categories{
    flex: 1;
    overflow-y: auto;
    ul{
      li{
        height: 36px;
        line-height: 36px;
        &.on{
          >div{
            background-color: var(--item-on-bg-color);
          }
        }
        >div{
          display: flex;
          justify-content: space-between;
          height: 100%;
          padding: 0 5px;
          max-width: 100%;
          .cate_name{
            display: flex;
            max-width: 100%;
            width: 0;
            flex: 1;
            .text{
              overflow: hidden;
              text-overflow: ellipsis;
              white-space: nowrap;
              height: 100%;
              cursor: pointer;
            }
            i{
              font-style: normal;
              margin-left: 5px;
            }
          }
          .action{
            display: flex;
            .el-button{
              display: none;
              color: var(--action-btn-color);
            }
            .el-button:nth-child(2){
              margin-left: 5px;
            }
          }
          &.isEditing{
            .action{
              .el-button{
                display: block;
              }
            }
            :deep(.el-input){
              padding: 5px 0;
            }
          }
          &:hover{
            background-color: var(--item-on-bg-color);
            .cate_name{
              color: var(--item-hover-color);
            }
            .action{
              .el-button{
                display: block;
              }
            }
          }
        }
      }
    }
  }
}

.delete_dialog_cont{
  .msg_tip{
    display: flex;
    color: #999;
    font-size: 13px;
    .el-icon{
      margin-top: 4px;
      margin-right: 10px;
      color: #f9a239;
      font-size: 14px;
    }
  }
}
.actions{
  display: flex;
  justify-content: center;
}
</style>
